﻿using System;
using System.Collections.ObjectModel;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using DataAccess;
using Entities;
using Common.Constants;

namespace Business
{
    public class ServiceBusiness
    {
        /// <summary>
        /// Gets the instance.
        /// </summary>
        /// <value>
        /// The instance.
        /// </value>
        public static ServiceBusiness Instance { get; private set; }
        /// <summary>
        /// Initializes the <see cref="ServiceBusiness" /> class.
        /// </summary>
        static ServiceBusiness() { Instance = new ServiceBusiness(); }

        /// <summary>
        /// Filters the specified keyword.
        /// </summary>
        /// <param name="keyword">The keyword.</param>
        /// <param name="includeInactive">if set to <c>true</c> [include inactive].</param>
        /// <returns></returns>
        public Collection<Service> Filter(string keyword, bool includeInactive)
        {
            var listResult = new Collection<Service>();
            Collection<Service> listService = includeInactive ? ListService(true) : ListService(false);

            const string digitPattern = "^[0-9]";
            const string aePattern = "^[a-eA-E]";
            const string fjPattern = "^[f-jF-J]";
            const string knPattern = "^[k-nK-N]";
            const string orPattern = "^[o-rO-R]";
            const string svPattern = "^[s-vS-V]";
            const string wzPattern = "^[w-zW-Z]";

            switch (keyword)
            {
                case "all":
                    return listService;
                case "09":
                    return DoFilter(digitPattern, listService);
                case "ae":
                    return DoFilter(aePattern, listService);
                case "fj":
                    return DoFilter(fjPattern, listService);
                case "kn":
                    return DoFilter(knPattern, listService);
                case "or":
                    return DoFilter(orPattern, listService);
                case "sv":
                    return DoFilter(svPattern, listService);
                case "wz":
                    return DoFilter(wzPattern, listService);
            }
            return listResult;
        }

        /// <summary>
        /// Lists the service.
        /// </summary>
        /// <param name="includeInactive">if set to <c>true</c> [include inactive].</param>
        /// <returns></returns>
        public Collection<Service> ListService(bool includeInactive)
        {
            return ServiceDataAccess.Instance.ListService(includeInactive);
        }

        /// <summary>
        /// Does the filter.
        /// </summary>
        /// <param name="pattern">The pattern.</param>
        /// <param name="listService">The list service.</param>
        /// <returns></returns>
        private Collection<Service> DoFilter(string pattern, Collection<Service> listService)
        {
            var query = from o in listService
                        where checkPattern(pattern, o.ServiceName)
                        select o;
            return new Collection<Service>(query.ToList());
        }

        /// <summary>
        /// Checks the pattern.
        /// </summary>
        /// <param name="pattern">The pattern.</param>
        /// <param name="target">The target.</param>
        /// <returns></returns>
        private bool checkPattern(string pattern, string target)
        {
            var myRegex = new Regex(pattern);
            var match = myRegex.Match(target);
            return match.Success;
        }

        /// <summary>
        /// Gets the type of the service.
        /// </summary>
        /// <param name="refValue">The ref value.</param>
        /// <returns></returns>
        public string GetServiceType(int refValue)
        {
            var result = ReferenceDataDataAccess.Instance.GetReferenceData((int) RefCode.ServiceType, refValue);
            return result.DataRef;
        }

        /// <summary>
        /// Pagings the specified page number.
        /// </summary>
        /// <param name="pageNumber">The page number.</param>
        /// <param name="pageSize">Size of the page.</param>
        /// <param name="listServices">The list services.</param>
        /// <returns></returns>
        public Collection<Service> Paging(int pageNumber, int pageSize, Collection<Service> listServices)
        {
            int totalPage = listServices.Count % pageSize == 0 ? listServices.Count / pageSize : listServices.Count / pageSize + 1;
            if (pageNumber <= totalPage)
            {
                return new Collection<Service>(listServices.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList());
            }
            return null;
        }

        /// <summary>
        /// Changes the status.
        /// </summary>
        /// <param name="serviceId">The service id.</param>
        /// <param name="isactive">if set to <c>true</c> [isactive].</param>
        /// <returns></returns>
        public bool ChangeStatus(Guid serviceId, bool isactive)
        {
            if (serviceId == Guid.Empty)
            {
                return false;
            }
            var result = ServiceDataAccess.Instance.ChangeStatus(serviceId, isactive);
            return result == 1;
        }

        /// <summary>
        /// Validates the name.
        /// </summary>
        /// <param name="serviceId">The service id.</param>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public bool ValidateName(Guid serviceId, string name)
        {
            if (String.IsNullOrEmpty(name))
            {
                return false;
            }
            var result = ServiceDataAccess.Instance.GetDifferentName(serviceId, name);
            if (result.Read())
            {
                return false;
            }
            return true;
        }

        /// <summary>
        /// Inserts the service.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        public bool InsertService(Service service,out string message)
        {
            message = "";
            if (service == null) return false;
            if (String.IsNullOrEmpty(service.ServiceName) || String.IsNullOrEmpty(service.ShortDescription) || String.IsNullOrEmpty(service.DeptCode) || service.ServiceType == 0)
            {
                return false;
            }
            try
            {
                if (!ValidateName(service.ServiceId, service.ServiceName))
                {
                    message = "Service Name cannot duplicate!";
                    return false;
                }
                var result = ServiceDataAccess.Instance.InsertService(service);
                return result > 0;
            }
            catch (SqlException exception)
            {
                message = exception.Message;
                return false;
            }


        }

        /// <summary>
        /// Updates the service.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        public bool UpdateService(Service service, out string message)
        {
            message = "";
            if (service == null)
            {
                message = "Service is not null!"; return false;
            }
            if (String.IsNullOrEmpty(service.ServiceName) || String.IsNullOrEmpty(service.ShortDescription) || String.IsNullOrEmpty(service.DeptCode))
            {
                message = "Service is not empty!";
                return false;
            }
            try
            {
                if (!ValidateName(service.ServiceId, service.ServiceName))
                {
                    message = "Service Name cannot duplicate!";
                    return false;
                }
                message = "Successfull!";
                var result = ServiceDataAccess.Instance.UpdateService(service);
                return result == 1;
            }
            catch (SqlException exception)
            {
                message = exception.Message;
                return false;
            }
        }

        /// <summary>
        /// Gets the by id.
        /// </summary>
        /// <param name="serviceId">The service id.</param>
        /// <returns></returns>
        public Service GetById(Guid serviceId)
        {
            if (serviceId == Guid.Empty)
            {
                return null;
            }
            try
            {
                return ServiceDataAccess.Instance.GetById(serviceId);
            }
            catch (SqlException)
            {

                return null;
            }


        }

        #region get reference data
        /// <summary>
        /// Gets the service subtype.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetServiceSubtype()
        {
            const int refCode = (int)RefCode.ServiceSubtype;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }
        public Collection<ReferenceData> GetServiceAttendance ()
        {
            const int refCode = (int)RefCode.ServiceAttendance;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }
        public Collection<ReferenceData> GetProcessMethod ()
        {
            const int refCode = (int)RefCode.ProcessMethod;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }
        /// <summary>
        /// Gets the type of the service.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetServiceType()
        {
            const int refCode = (int)RefCode.ServiceType;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the contract outcome.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetContractOutcome()
        {
            const int refCode = (int)RefCode.ContractOutcome;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the contract obligation.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetContractObligation()
        {
            const int refCode = (int)RefCode.ContractObligation;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the service benefits criterion.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetServiceBenefitsCriterion()
        {
            const int refCode = (int)RefCode.ServiceBenefitsCriterion;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the service barriers criterion.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetServiceBarriersCriterion()
        {
            const int refCode = (int)RefCode.ServiceBarriersCriterion;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the service ethnicity criterion.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetServiceEthnicityCriterion()
        {
            const int refCode = (int)RefCode.ServiceEthnicityCriterion;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the service disability criterion.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetServiceDisabilityCriterion()
        {
            const int refCode = (int)RefCode.ServiceDisabilityCriterion;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the service personal circumstances criterion.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetServicePersonalCircumstancesCriterion()
        {
            const int refCode = (int)RefCode.ServicePersonalCircumstancesCriterion;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the other service participation criterion.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetOtherServiceParticipationCriterion()
        {
            const int refCode = (int)RefCode.ServicePersonalCircumstancesCriterion;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the client support process.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetClientSupportProcess()
        {
            const int refCode = (int)RefCode.ClientSupportProcess;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the client outcome.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetClientOutcome()
        {
            const int refCode = (int)RefCode.ClientSupportProcess;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the target client.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetTargetClient()
        {
            const int refCode = (int)RefCode.TargetClient;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the referral sources.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetReferralSources()
        {
            const int refCode = (int)RefCode.ReferralSources;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the support centres.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetSupportCentres()
        {
            const int refCode = (int)RefCode.SupportCentres;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }

        /// <summary>
        /// Gets the funding source.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetFundingSource()
        {
            const int refCode = (int)RefCode.FundingSource;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }
        /// <summary>
        /// Gets the client journey.
        /// </summary>
        /// <returns></returns>
        public Collection<ReferenceData> GetClientJourney()
        {
            const int refCode = (int)RefCode.ClientJourney;
            return ReferenceDataDataAccess.Instance.GetReferenceData(refCode);
        }
        /// <summary>
        /// Gets the other service.
        /// </summary>
        /// <returns></returns>
        public Collection<Service> GetOtherService()
        {
            try
            {
                return ServiceDataAccess.Instance.ListService(true);
            }
            catch (SqlException)
            {
                return null;
            }

        }

        /// <summary>
        /// Gets the intervention all.
        /// </summary>
        /// <returns></returns>
        public Collection<Intervention> GetInterventionAll()
        {

            var lstService = ServiceDataAccess.Instance.ListService(false);
            var interventionId = (from service in lstService
                                  select service.InterventionId).ToList();
            var lstIntervention = from t in InterventionDataAccess.Instance.ListIntervention()
                                  where !interventionId.Contains(t.InterventionId.ToString()) && t.IsActive
                                  select t;


            return new Collection<Intervention>(lstIntervention.ToList());
        }
        /// <summary>
        /// Gets the intervention all.
        /// </summary>
        /// <param name="serviceId">The service id.</param>
        /// <returns></returns>
        public Collection<Intervention> GetInterventionAll(Guid serviceId)
        {
            string currentInterventionId = string.Empty;
            var lstService = ServiceDataAccess.Instance.ListService(false);
            var interventionId = (from service in lstService
                                  where service.ServiceId != serviceId
                                  select service.InterventionId).ToList();
            var currentIntervention = lstService.SingleOrDefault(c => c.ServiceId == serviceId);
            if (currentIntervention != null)
                currentInterventionId = currentIntervention.InterventionId;

            var lstIntervention = from t in InterventionDataAccess.Instance.ListIntervention()
                                  where !interventionId.Contains(t.InterventionId.ToString()) || currentInterventionId.IndexOf(t.InterventionId.ToString(),StringComparison.OrdinalIgnoreCase) >= 0 && t.IsActive
                                  select t;


            return new Collection<Intervention>(lstIntervention.ToList());
        }

        #endregion
    }
}
